package com.yu.crm.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.whyxzz.arcface.ArcFace;
import com.yu.crm.domain.pojo.CrmDevice;
import com.yu.crm.domain.pojo.CrmEigenvalue;
import com.yu.crm.mapper.CrmEigenvalueMapper;
import com.yu.crm.service.CrmBlacklistUserService;
import com.yu.crm.service.CrmUserService;
import com.yu.crm.utils.DateUtils;
import com.yu.crm.utils.EigenValue;
import com.yu.crm.ws.WebSocketClient;
import com.yu.crm.ws.WsMessage;
import com.yu.crm.ws.pw.WebSocketManagerPW;
import com.yxzz.common.config.UserCacheManager;
import com.yxzz.common.exception.GeneralException;
import com.yxzz.common.helper.DataHelpers;
import com.yxzz.common.helper.DateHelpers;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 人脸特征值对比表 服务实现类
 * </p>
 *
 * @author ct
 * @since 2019-12-23
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CrmEigenvalueService extends ServiceImpl<CrmEigenvalueMapper, CrmEigenvalue> {
    @Autowired
    ObjectMapper objectMapper;
    @Autowired
    WebSocketClient webSocketClient;
    @Autowired
    UserCacheManager userCacheManager;
    @Autowired
    CrmDeviceService crmDeviceService;
    @Autowired
    AttendanceRecordService attendanceRecordService;
    @Autowired
    CrmUserService crmUserService;
    @Autowired
    CallerReservationPeopleService callerReservationPeopleService;

    @Autowired
    CrmBlacklistUserService crmBlacklistUserService;


    public void add(CrmEigenvalue crmEigenvalue) {
        //Boolean flag=false;
        crmEigenvalue.setGmtCreate(LocalDateTime.now());
       if(DataHelpers.isNotEmpty(crmEigenvalue.getCameraFeature())){
            crmEigenvalue.setImgBase(Base64.decodeBase64(crmEigenvalue.getCameraFeature()));
           //flag=true;
        }
        baseMapper.insert(crmEigenvalue);
        /*if(flag){
           if(DataHelpers.isNotEmpty(crmEigenvalue.getType()) && DataHelpers.isNotEmpty(crmEigenvalue.getUserId())){
                webSocketClient.sendMessageCameraFeature(crmEigenvalue.getCameraFeature(),"",crmEigenvalue.getUserId(),"",2);
           }
        }*/
    }

    public void update(CrmEigenvalue crmEigenvalue) {
        Boolean flag=false;
        crmEigenvalue.setGmtModified(LocalDateTime.now());
        if(DataHelpers.isNotEmpty(crmEigenvalue.getCameraFeature())){
            crmEigenvalue.setCertificateEigen(Base64.decodeBase64(crmEigenvalue.getCameraFeature()));
            flag=true;
       }
        if(flag){
            CrmEigenvalue crmEigenvalue1 = baseMapper.selectById(crmEigenvalue.getId());
            if(DataHelpers.isNotEmpty(crmEigenvalue1.getType()) && DataHelpers.isNotEmpty(crmEigenvalue1.getUserId())){
                String cameraFeature = Base64.encodeBase64String(crmEigenvalue1.getCertificateEigen());
                webSocketClient.sendMessageCameraFeature(cameraFeature,"",crmEigenvalue1.getUserId(),"",2);
            }
        }
        baseMapper.updateById(crmEigenvalue);
    }

    /**
     * 通过用户id修改
     * @param crmEigenvalue
     */
    public void updateByUserId(CrmEigenvalue crmEigenvalue) {
        QueryWrapper<CrmEigenvalue> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("is_deleted",0);
        queryWrapper.and(x->
                x.eq("user_id",crmEigenvalue.getUserId())
                .or().eq("open_id",crmEigenvalue.getOpenId()));

        Boolean flag=false;
        crmEigenvalue.setGmtModified(LocalDateTime.now());
        if(DataHelpers.isNotEmpty(crmEigenvalue.getCameraFeature())){
            crmEigenvalue.setCertificateEigen(Base64.decodeBase64(crmEigenvalue.getCameraFeature()));
            flag=true;
        }

        if(flag){
            CrmEigenvalue crmEigenvalue1 = baseMapper.selectById(crmEigenvalue.getId());
            if(DataHelpers.isNotEmpty(crmEigenvalue1.getType()) && DataHelpers.isNotEmpty(crmEigenvalue1.getUserId())){
                String cameraFeature = Base64.encodeBase64String(crmEigenvalue1.getCertificateEigen());
                webSocketClient.sendMessageCameraFeature(cameraFeature,"",crmEigenvalue1.getUserId(),"",2);
            }
        }
        baseMapper.update(crmEigenvalue,queryWrapper);
    }

    public void deleteById(Long id) {
        CrmEigenvalue crmEigenvalue = new CrmEigenvalue();
        crmEigenvalue.setGmtModified(LocalDateTime.now());
        crmEigenvalue.setIsDeleted(1);

        QueryWrapper<CrmEigenvalue> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        queryWrapper.eq("is_deleted", 0);
        baseMapper.update(crmEigenvalue, queryWrapper);
    }

    public CrmEigenvalue infoById(Long id) {
        return baseMapper.selectById(id);
    }

    public List<CrmEigenvalue> listCrmEigenvalue(){
        QueryWrapper<CrmEigenvalue> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("is_deleted",0);
        return baseMapper.selectList(queryWrapper);
    }

    public List<CrmEigenvalue> listCrmEigenvalueByType(Integer type){
        QueryWrapper<CrmEigenvalue> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("type",type);
        queryWrapper.eq("is_deleted",0);
        return baseMapper.selectList(queryWrapper);
    }

    public List<CrmEigenvalue> listCrmEigenvalueByUserId(String userId) {
        QueryWrapper<CrmEigenvalue> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        queryWrapper.eq("is_deleted",0);
        return baseMapper.selectList(queryWrapper);
    }

    /**
     * 通过人脸特征值查询记录
     * @param b 人脸特征值
     * @return
     */
    public List<CrmEigenvalue> listCrmEigenvalueByEigenvalue(byte[] b) {
        QueryWrapper<CrmEigenvalue> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("certificate_eigen",b);
        queryWrapper.eq("is_deleted",0);
        return baseMapper.selectList(queryWrapper);
    }

    /**
     * 通过特征值集合开门
     * @param map
     */
    public void openDeviceByEigenvalue(HashMap<String,Object> map){
        //String uid = userCacheManager.getCurrentUser().getUserId();
        ArcFace arcFace = EigenValue.initArcFace();
        if(DataHelpers.isEmpty(arcFace)){
            throw new GeneralException("ArcFace初始化失败");
        }
        List<String> userList = new ArrayList<>();
        //查询和预约时间相同的人脸特征值列表
        QueryWrapper<CrmEigenvalue> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted",0);
        queryWrapper.eq("type",2);
        List<CrmEigenvalue> crmEigenvalues = baseMapper.selectList(queryWrapper);
        if(DataHelpers.isNotEmpty(crmEigenvalues)){
            try {
                String cameraNumber= map.get("cameraNumber").toString();
                String cameraImageBase64= map.get("cameraImageBase64").toString();
                List<HashMap<String,Object>> mapList= objectMapper.readValue(objectMapper.writeValueAsString(map.get("eigenvalues")), new TypeReference<List<HashMap<String,Object>>>(){});
                System.out.println("=====eigenvalues{}====="+mapList.size());
                if(DataHelpers.isNotEmpty(mapList)){
                    Boolean flag=false;
                    //陌生人集合
                    for (HashMap<String,Object> map1:mapList) {
                       /* CrmEigenvalue crmEigenvalue=new CrmEigenvalue();
                        String id =null;
                        String imgBase64 =null;*/
                        String cameraFeature =null;
                        // 性别 0：男 1：女 -1: 不确定
                        Integer gender=-1;
                        // 人员年龄 0: 不确定 > 0: 确定的年龄
                        Integer age=0;

                        /*if(DataHelpers.isNotEmpty(map1.get("id"))){
                            id=map1.get("id").toString();
                        }
                        if(DataHelpers.isNotEmpty(map1.get("gender"))){
                            gender=Integer.parseInt(map1.get("gender").toString());
                        }
                        if(DataHelpers.isNotEmpty(map1.get("age"))){
                            age=Integer.parseInt(map1.get("age").toString());
                        }*/
                        if(DataHelpers.isNotEmpty(map1.get("cameraFeature"))){
                            cameraFeature =map1.get("cameraFeature").toString();
                        }
                        //图片base64格式
                        /*if(DataHelpers.isNotEmpty(map1.get("imgBase64"))){
                            imgBase64 =map1.get("imgBase64").toString();
                        }*/
                        byte[] bytes = Base64.decodeBase64(cameraFeature);
                        String userId = "";
                        String openId = "";
                        if (DataHelpers.isNotEmpty(bytes)) {
                            for (CrmEigenvalue eigenvalue : crmEigenvalues) {
                                if (DataHelpers.isNotEmpty(eigenvalue) && DataHelpers.isNotEmpty(eigenvalue.getCertificateEigen())) {
                                    if (arcFace.compareFaceFeature(bytes, eigenvalue.getCertificateEigen())) {
                                        if (eigenvalue.getType().toString().equals("2")) {
                                            flag = true;
                                            //判断是否是内部人员
                                            if (!userList.contains(eigenvalue.getUserId())) {
                                                userList.add(eigenvalue.getUserId());
                                            }
                                        }else if (eigenvalue.getType().toString().equals("1")) {
                                            flag = true;
                                        }
                                       /* //比对成功
                                        switch (eigenvalue.getType()) {
                                            case 1:
                                                //访客有openId 公众号预约
                                                flag = true;
                                                openId = eigenvalue.getOpenId();
                                                crmEigenvalue.setType(1);
                                                break;
                                            case 2:
                                                if (DataHelpers.isNotEmpty(eigenvalue.getUserId())) {
                                                    userId = eigenvalue.getUserId();
                                                }
                                                flag = true;
                                                //判断是否是内部人员
                                                if (!userList.contains(eigenvalue.getUserId())) {
                                                    userList.add(eigenvalue.getUserId());
                                                }
                                                crmEigenvalue.setType(2);
                                                break;
                                            case 3:
                                                //陌生人之前有记录 再次新增记录  获取之前的userId
                                                if (DataHelpers.isNotEmpty(eigenvalue.getUserId())) {
                                                    userId = eigenvalue.getUserId();
                                                }else {
                                                    //陌生人之前没有记录
                                                    userId = UUID.randomUUID().toString().replace("-", "");
                                                }
                                                crmEigenvalue.setType(3);
                                                break;
                                            default:
                                                break;
                                        }*/
                                    }else {
                                        //陌生人之前没有记录
                                        System.out.println("----比对失败---");
                                    }
                                }
                            }
                        }
                       /* System.out.println(userId);
                        crmEigenvalue.setOpenId(openId);
                        crmEigenvalue.setUserId(userId);
                        crmEigenvalue.setCameraImageBase(cameraImageBase64);
                        if(DataHelpers.isNotEmpty(bytes)){
                            crmEigenvalue.setCertificateEigen(bytes);
                        }
                        if(DataHelpers.isNotEmpty(gender)){
                            crmEigenvalue.setGender(gender);
                        }
                        if(DataHelpers.isNotEmpty(age)){
                            crmEigenvalue.setAge(age);
                        }
                        if(DataHelpers.isNotEmpty(imgBase64)){
                            crmEigenvalue.setImgBase(Base64.decodeBase64(imgBase64));
                        }
                        crmEigenvalue.setCameraNumber(cameraNumber);
                        crmEigenvalue.setGmtCreate(LocalDateTime.now());
                        //新增陌生人特征值记录
                        baseMapper.insert(crmEigenvalue);*/
                    }

                    if(flag){
                        //访客和内部人员执行开门
                        System.out.println("=======================>>>>>>>>>>开门");
                        crmDeviceService.openDevice(cameraNumber);
                    }
                }
                /**
                 * 新增考勤记录
                 */
                if (DataHelpers.isNotEmpty(userList)) {
                    attendanceRecordService.add(JSONObject.toJSONString(userList));
                }
            }catch (GeneralException e){
                e.printStackTrace();
                throw new GeneralException(e.getMessage());
            }catch (Exception e){
                e.printStackTrace();
                throw new GeneralException("转换失败");
            }
        }
    }


    public void aaa() {
        List<String> userList = new ArrayList<>();
//        userList.add("ZuoShouDaoYing");
        userList.add("admin");
/*        Map<String,Object> userMap = new HashMap<>();
        userMap.put("userId",userList);*/
        attendanceRecordService.add(JSONObject.toJSONString(userList));
    }

    //保存特征值流水
    public void saveEigenvalue(HashMap<String, Object> map) {
        ArcFace arcFace = EigenValue.initArcFace();
        if(DataHelpers.isEmpty(arcFace)){
            throw new GeneralException("ArcFace初始化失败");
        }
        try {
            String cameraNumber= map.get("cameraNumber").toString();
            List<HashMap<String,Object>> mapList= objectMapper.readValue(objectMapper.writeValueAsString(map.get("eigenvalues")), new TypeReference<List<HashMap<String,Object>>>(){});
            if(DataHelpers.isNotEmpty(mapList)){
                List<CrmEigenvalue> crmEigenvalueList = new ArrayList<>();
                //陌生人集合
                for (HashMap<String,Object> map1:mapList) {
                    String imgBase64 =null;
                    String cameraFeature =null;
                    // 性别 0：男 1：女 -1: 不确定
                    Integer gender=-1;
                    // 人员年龄 0: 不确定 > 0: 确定的年龄
                    Integer age=0;
                    if(DataHelpers.isNotEmpty(map1.get("gender"))){
                        gender=Integer.parseInt(map1.get("gender").toString());
                    }
                    if(DataHelpers.isNotEmpty(map1.get("age"))){
                        age=Integer.parseInt(map1.get("age").toString());
                    }
                    if(DataHelpers.isNotEmpty(map1.get("cameraFeature"))){
                        cameraFeature =map1.get("cameraFeature").toString();
                    }
                    //图片base64格式
                    if(DataHelpers.isNotEmpty(map1.get("imgBase64"))){
                        imgBase64 =map1.get("imgBase64").toString();
                    }
                    byte[] bytes = Base64.decodeBase64(cameraFeature);
                    if (DataHelpers.isNotEmpty(bytes)) {
                        //判断当前特征值是否是内部人员
                        CrmEigenvalue crmEigenvalue = new CrmEigenvalue();
                        crmEigenvalue.setIsDeleted(0);
                        if(DataHelpers.isNotEmpty(bytes)){
                            crmEigenvalue.setCertificateEigen(bytes);
                        }
                        if(DataHelpers.isNotEmpty(imgBase64)){
                            crmEigenvalue.setImgBase(Base64.decodeBase64(imgBase64));
                        }
                        if(DataHelpers.isNotEmpty(gender)){
                            crmEigenvalue.setGender(gender);
                        }
                        if(DataHelpers.isNotEmpty(age)){
                            crmEigenvalue.setAge(age);
                        }
                        crmEigenvalue.setCameraNumber(cameraNumber);
                        crmEigenvalue.setGmtCreate(DateHelpers.now());

                        String isUser = crmUserService.isUser(bytes,arcFace);
                        if (DataHelpers.isNotEmptyString(isUser)) {
                            //内部员工
                            crmEigenvalue.setUserId(isUser);
                            crmEigenvalue.setType(2);
                        }
                        //判断是否为访客
                        String isCaller = callerReservationPeopleService.isCaller(bytes,arcFace);
                        if (DataHelpers.isNotEmptyString(isCaller)) {
                            crmEigenvalue.setOpenId(isCaller);
                            crmEigenvalue.setType(1);
                        }
                        //判断是否是黑名单人员
                        String isBlacker = crmBlacklistUserService.isBlack(bytes, arcFace);
                        if (DataHelpers.isNotEmptyString(isBlacker)) {
                            crmEigenvalue.setUserId(isBlacker);
                            crmEigenvalue.setType(4);

                            CrmDevice crmDevice = crmDeviceService.infoByCameraNumber(crmEigenvalue.getCameraNumber());
                            if (crmDevice!=null) {
                                crmEigenvalue.setBuildingAreaName(crmDevice.getBuildingAreaName());
                                crmEigenvalue.setBuildingFloorName(crmDevice.getBuildingFloorName());
                                crmEigenvalue.setBuildingName(crmDevice.getBuildingName());

                            }

                            //websocket推数据
                            WsMessage wsMessage = new WsMessage();
                            wsMessage.setContent(crmEigenvalue);
                            WebSocketManagerPW.sendMessage(wsMessage);

                        }

                        if (DataHelpers.isEmptyString(isUser) && DataHelpers.isEmptyString(isCaller)) {
                            //陌生人
                            crmEigenvalue.setUserId(UUID.randomUUID().toString().replace("-", ""));
                            crmEigenvalue.setType(3);
                        }
                        crmEigenvalueList.add(crmEigenvalue);
                    }
                }
                if (crmEigenvalueList.size()>0) {
                    this.saveBatch(crmEigenvalueList);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new GeneralException("转换失败");
        }
    }


    /**
     * 分类查询 类别查询
     *
     * @param page
     * @param queryInfo
     * @return
     */
    public IPage<CrmEigenvalue> pageByQueryInfo(Page<CrmEigenvalue> page, CrmEigenvalue queryInfo) {

        return baseMapper.pageByQueryInfo(page, queryInfo);
    }


    /**
     * list 综合查询根据特征值  返回list 分页前端去做
     */
    public List<CrmEigenvalue> listByQueryInfo(CrmEigenvalue queryInfo) {

        List<CrmEigenvalue> crmEigenvalues = baseMapper.listByQueryInfo(queryInfo);


        //如果查询条件中有特征值的则进行比对
       if (queryInfo.getCertificateBase()!=null){
           //
            ArcFace arcFace = EigenValue.initArcFace();
            if (DataHelpers.isEmpty(arcFace)) {
                throw new GeneralException("ArcFace初始化失败");
            }
           byte[] bytes = EigenValue.extractFeature(queryInfo.getCertificateBase());
           List<CrmEigenvalue> results = new ArrayList<>();
            for (CrmEigenvalue crmEigenvalue : crmEigenvalues) {

                if (crmEigenvalue.getCertificateEigen()!=null&&arcFace.compareFaceFeature(bytes, crmEigenvalue.getCertificateEigen())) {
                    results.add(crmEigenvalue);
                }
            }
            return results;
        }else {
            return crmEigenvalues;
        }

    }


}